﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.Collections;

namespace DienLib.SummitLib
{
    /// <summary>
    /// Wrapper for UnitTextBox Summit UserControl
    /// </summary>
    public class TreeNodesCollection
    {
        private object _refobj;
        private Control _reftree;
        //private UltraTreeNode[] _refnode; // No Private Var use because Node in _refobj can change, may add more, or delete more. So better call Reflector everytime want to check tree.

        public TreeNodesCollection(object refTreeNodesCollection, Control refUltraTreeView)
        {
            _refobj = refTreeNodesCollection;
            _reftree = refUltraTreeView;
        }

        public int Count
        {
            get
            {
                if (_reftree.InvokeRequired) return (int)_reftree.Invoke((Func<int>)delegate { return DienLib.Reflector.GetProperty<int>(_refobj, "Count"); });
                else return DienLib.Reflector.GetProperty<int>(_refobj, "Count");
            }
        }

        public UltraTreeNode this[int index]
        {
            get
            {
                // Have to call reflector everytime want to check tree. No use private var because node can change, add more, delete, ..v..v..
                if (_reftree.InvokeRequired) return new UltraTreeNode((object)_reftree.Invoke((Func<object>)delegate { return DienLib.Reflector.GetThisIndexer<object>(_refobj, index); }), _reftree);
                else return new UltraTreeNode(DienLib.Reflector.GetThisIndexer<object>(_refobj, index), _reftree);
            }
        }

        public UltraTreeNode this[string key]
        {
            get
            {
                // Have to call reflector everytime want to check tree. No use private var because node can change, add more, delete, ..v..v..
                if (_reftree.InvokeRequired) return new UltraTreeNode((object)_reftree.Invoke((Func<object>)delegate { return DienLib.Reflector.GetThisIndexer<object>(_refobj, key); }), _reftree);
                else return new UltraTreeNode(DienLib.Reflector.GetThisIndexer<object>(_refobj, key), _reftree);
            }
        }

        public NodeEnumerator GetEnumerator()
        {
            if (_reftree.InvokeRequired) return new NodeEnumerator(_reftree.Invoke((Func<object>)delegate { return DienLib.Reflector.DoMethod<object>(_refobj, "GetEnumerator"); }), _reftree);
            else return new NodeEnumerator(DienLib.Reflector.DoMethod<object>(_refobj, "GetEnumerator"), _reftree);
        }

        #region DISPOSE METHOD
        // Dispose() calls Dispose(true)
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // NOTE: Leave out the finalizer altogether if this class doesn't 
        // own unmanaged resources itself, but leave the other methods
        // exactly as they are. 
        ~TreeNodesCollection()
        {
            // Finalizer calls Dispose(false)
            Dispose(false);
        }

        // The bulk of the clean-up code is implemented in Dispose(bool)
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // free managed resources, (detach event ?)
                if (this._refobj != null) this._refobj = null; // Khong keu this._refobj.Dispose vi Reference toi object do. Ngoai ra do pass reference nen this._refobj = null khong anh huong gi toi object goc
                if (this._reftree != null) this._reftree = null;
            }

            /* free native resources if there are any.
            if (nativeResource != IntPtr.Zero) 
            {
                Marshal.FreeHGlobal(nativeResource);
                nativeResource = IntPtr.Zero;
            }*/
        }
        #endregion
    }

    public class NodeEnumerator //: DisposableObjectEnumeratorBase
    {
        object _refobj; Control _reftree; 
        public NodeEnumerator(object refNodeEnumerator, Control refUltraTreeView)
        {
            _refobj = refNodeEnumerator;
            _reftree = refUltraTreeView;
        }

        public UltraTreeNode Current
        {
            get
            {
                if (_reftree.InvokeRequired) return new UltraTreeNode(_reftree.Invoke((Func<object>)delegate { return DienLib.Reflector.GetProperty<object>(_refobj, "Current"); }), _reftree);
                else return new UltraTreeNode(DienLib.Reflector.GetProperty<object>(_refobj, "Current"), _reftree); // Does it really need Invoke ?
            }
        }

        public bool MoveNext() // from DisposableObjectEnumeratorBase
        {
            if (_reftree.InvokeRequired) return (bool)_reftree.Invoke((Func<bool>)delegate { return DienLib.Reflector.DoMethod<bool>(_refobj, "MoveNext"); });
            else return DienLib.Reflector.DoMethod<bool>(_refobj, "MoveNext");
        }

        public void Reset() // from DisposableObjectEnumeratorBase
        {
            if (_reftree.InvokeRequired) _reftree.Invoke((MethodInvoker)delegate { DienLib.Reflector.DoMethod(_refobj, "Reset"); });
            else DienLib.Reflector.DoMethod(_refobj, "Reset");
        }
    }
}